/**
 * Global variables used by jClass
 */
window["_"] = {
    LIB : "/libraries/",
    RESERVED : ["_typeId", "_typeName", "_extending", "prototype", "_prototype"],
    id : 0,
    contextID : 0
};
window['IE'] = navigator.userAgent.match(/MSIE/) !== null;
window['END'] = '';

/**
 * Get/Set jClass configuration
 *
 * Usage:
 *    iniset('LIB', '/path/to/my/libraires/');
 *    include("my.namespace");
 *
 *    document.write(iniget('LIB'));
 */
var iniset = function(config, value) { _[config] = value; };
var iniget = function(config) { return _[config]; };

/**
 * Some comaptibility issues to
 */
if (typeof Array.indexOf === 'undefined')
    Array.prototype.indexOf = function(val) { for (var i = 0; i < this.length; i++) { if (this[i] == val) return i;} return -1;};

/**
 * Loads javascript files at runtime
 *
 * Usage:
 *    require("myJsClass.js"[, "myOtherJsClass.js", ...]);
 *    include("myJsClass.js"[, "myOtherJsClass.js", ...]);
 */

var include = function() {
    if (!document.getElementById) return;
    if (typeof (_.loadedObjects) === 'undefined') _.loadedObjects = "";
    var rootPath = iniget('LIB'), path;
    for (var i = 0; i < arguments.length; i++) {
        function appendChild(node, text) { if (null === node.canHaveChildren || node.canHaveChildren) { node.appendChild(document.createTextNode(text)); } else { node.text = text; }}
        var file = arguments[i],
            fileRef = window.document.createElement("script");
            fileRef.setAttribute("type", "text/javascript");
        if (_.loadedObjects.indexOf(file) == -1) {
            if (file.indexOf(".js") != -1) {
                path = file;
            } else {
                if (file.match(/^.[a-zA-Z\.]*$/)) {
                    if (rootPath.match(/\/$/) === null) {
                        rootPath += '/';
                    }
                    path = rootPath + file.replace(/\./g, "/") + ".js";
                }
            }
            if (fileRef !== undefined) {
                var oXML = getXMLHttpObj();
                oXML.open('GET', path, false);
                oXML.send('');

                if (IE) {
                   document.write("<script type='text/javascript' src='"+ path +"'></script>");
                   eval(__prepareInclude(oXML.responseText));
                } else {
                    var head = document.getElementsByTagName("head")[0] || document.documentElement;
                    head.insertBefore(fileRef, head.firstChild);
                    appendChild(fileRef, __prepareInclude(oXML.responseText));
                }
                 _.loadedObjects += "[" + path + "]";
            }
        }
    }
};

var __prepareInclude = function(body) {
    var iteration = 'for (var __cls in namespace) eval("var " + __cls + " = namespace." + __cls);';
    var val = "(function() {\n";
    var match = body.match(/(?:use\(['"])(.[^"]*)(?:['"]\);)/g);
    if (match) {
        for (var i = 0; i < match.length; i++) {
            var ns = match[i].match(/(?:use\(['"])(.[^"]*)(?:['"]\);)/)[1];
            body = body.replace(match[i], iteration.replace(/namespace/g, ns));
        }
    }
    val += body + ";";
    val += "\n})(this);";
    return val;
};

var use = function(namespace) { throw "You can call `use` only in files loaded with `include` method"; };

include(
    "/jClass/jUtils.js",
    "/jClass/jClassId.js",
    "/jClass/jInterface.js",
    "/jClass/jEnum.js",
    "/jClass/jModifiers.js",
    "/jClass/jClassMain.js"
);

/**
 * Namespaces
 */
function namespace(name) {
    var x = name.split("."), tmp = window;
    for (var i = 0; i < x.length; i++) {
        if (typeof tmp[x[i]] === 'undefined') {
            tmp[x[i]] = new Object();
        }
        tmp = tmp[x[i]] || {};
    }
    return function(namespacebody) {
        for (var prop in namespacebody) {
           tmp[prop] = namespacebody[prop]
        }
    }
}

function getXMLHttpObj(){
	if(typeof(XMLHttpRequest)!='undefined') {
		return new XMLHttpRequest();
    }
	var axO = ['Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'], i;
	for (i = 0; i < axO.length; i++) {
		try{
			return new ActiveXObject(axO[i]);
		}catch(e){}
    }
	return null;
}
